package com.chenfan.process.client;

/**
 * @author K
 * @date 2021/3/5
 */

import com.chenfan.ccp.common.result.R;
import com.chenfan.process.dto.*;
import com.chenfan.process.vo.*;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author K
 * @date 2021/2/26
 */
@FeignClient(name = "chenfan-cloud-process", url = "${feign.process:}")
public interface ProcessClient {

    /**
     * 发起审批
     *
     * @param approvalTemplateId
     *            审批模板id
     * @param useId
     *            用户id
     * @param userName
     *            用户名
     * @param param
     *            参数
     * @return 审批实例ID {@link R}<{@link Long}>
     */
    @Deprecated
    @ApiOperation("发起审批")
    default R<Long> startProcess(Long approvalTemplateId, Long useId, String userName, String param) {
        return startProcess(approvalTemplateId.toString(), ApprovalDTO.builder().useId(useId).userName(userName)
            .param(ApprovalDTO.Params.builder().parameter(param).build()).build());
    }

    default R<Long> startProcess(Long approvalTemplateId, Long useId, String userName, String param, Long businessId,
                                 String businessCode, String businessParam) {
        return startProcess(approvalTemplateId.toString(), ApprovalDTO.builder().useId(useId).userName(userName)
                .param(ApprovalDTO.Params.builder().parameter(param).build())
                .businessId(businessId)
                .businessCode(businessCode)
                .businessParam(businessParam)
                .build());
    }

    @Deprecated
    @ApiOperation("发起审批")
    default R<Long> startProcess(String approvalTemplateCode, Long useId, String userName, String param) {
        return startProcess(approvalTemplateCode, ApprovalDTO.builder().useId(useId).userName(userName)
                .param(ApprovalDTO.Params.builder().parameter(param).build()).build());
    }

    /**
     * 发起审批, 用于发起的时候自选人的时候使用
     *
     * @param approvalTemplateId
     *            审批模板id
     * @param startUser
     *            发起用户
     * @param nextUser
     *            自选用户
     * @param param
     *            参数
     * @return {@link R}<{@link Long}>
     */
    @Deprecated
    default R<Long> startProcess(Long approvalTemplateId, StartUserDTO startUser, StartUserDTO nextUser, String param) {
        return startProcess(approvalTemplateId.toString(),
            ApprovalDTO.builder().useId(startUser.getUserId()).userName(startUser.getUserName())
                .nextUserId(nextUser.getUserId()).nextUserName(nextUser.getUserName())
                .param(ApprovalDTO.Params.builder().parameter(param).build()).build());
    }

    default R<Long> startProcess(Long approvalTemplateId, StartUserDTO startUser, StartUserDTO nextUser, String param,
                                 Long businessId, String businessCode, String businessParam) {
        return startProcess(approvalTemplateId.toString(),
                ApprovalDTO.builder().useId(startUser.getUserId()).userName(startUser.getUserName())
                        .nextUserId(nextUser.getUserId()).nextUserName(nextUser.getUserName())
                        .param(ApprovalDTO.Params.builder().parameter(param).build())
                        .businessId(businessId)
                        .businessCode(businessCode)
                        .businessParam(businessParam)
                        .build());
    }

    @Deprecated
    default R<Long> startProcess(String approvalTemplateCode, StartUserDTO startUser, StartUserDTO nextUser, String param) {
        return startProcess(approvalTemplateCode,
                ApprovalDTO.builder().useId(startUser.getUserId()).userName(startUser.getUserName())
                        .nextUserId(nextUser.getUserId()).nextUserName(nextUser.getUserName())
                        .param(ApprovalDTO.Params.builder().parameter(param).build()).build());
    }

    /**
     * 发起审批
     *
     * @param approvalTemplateId
     *            审批模板id
     * @param useId
     *            用户id
     * @param userName
     *            用户名
     * @param param
     *            参数
     * @param checkField
     *            检查参数
     * 
     * @return 审批实例ID {@link R}<{@link Long}>
     */
    @Deprecated
    default R<Long> startProcess(Long approvalTemplateId, Long useId, String userName, String param,
        String checkField) {
        return startProcess(approvalTemplateId.toString(),
            ApprovalDTO.builder().useId(useId).userName(userName)
                .param(ApprovalDTO.Params.builder().parameter(param).build())
                .checkField(ApprovalDTO.CheckField.builder().checkFields(checkField).build()).build());
    }

    default R<Long> startProcess(Long approvalTemplateId, Long useId, String userName, String param,
                                 String checkField, Long businessId, String businessCode, String businessParam) {
        return startProcess(approvalTemplateId.toString(),
                ApprovalDTO.builder().useId(useId).userName(userName)
                        .param(ApprovalDTO.Params.builder().parameter(param).build())
                        .checkField(ApprovalDTO.CheckField.builder().checkFields(checkField).build())
                        .businessId(businessId)
                        .businessCode(businessCode)
                        .businessParam(businessParam)
                        .build());
    }

    @Deprecated
    default R<Long> startProcess(String approvalTemplateCode, Long useId, String userName, String param,
                                 String checkField) {
        return startProcess(approvalTemplateCode,
                ApprovalDTO.builder().useId(useId).userName(userName)
                        .param(ApprovalDTO.Params.builder().parameter(param).build())
                        .checkField(ApprovalDTO.CheckField.builder().checkFields(checkField).build()).build());
    }

    /**
     * 撤销批准
     *
     * @param approvalId
     *            审批实例id
     * @param userId
     *            用户id
     * @param userName
     *            用户名
     * @return {@link R}<{@link Long}>
     */
    @ApiOperation("撤回审批")
    default R<Long> revokeApproval(Long approvalId, Long userId, String userName) {
        return revokeApproval(approvalId, UserDTO.builder().userId(userId).userName(userName).build());
    }

    /**
     * 获取实例状态列表
     *
     * @param approvalTemplateId
     *            审批模板id
     * @param approvalUserId
     *            当前审批的id
     * @return {@link R}<{@link List}<{@link ApprovalVo}>>
     */
    @ApiOperation("据状态筛选审批单")
    default R<List<ApprovalVo>> getInstanceStatusList(Long approvalTemplateId, Long approvalUserId) {
        return getInstanceStatusList(approvalTemplateId, approvalUserId, 1, Integer.MAX_VALUE);
    }

    /**
     * 根据审批实例查询当前审批的人员
     *
     * @param approvalIdList
     *            审批实例id列表
     * @return {@link R}<{@link Map}<{@link Long}, {@link String}>>
     */
    @ApiOperation("查询审批人")
    default R<Map<Long, String>> approvalToMap(Collection<Long> approvalIdList) {
        return approvalToMap(ApprovalMapDTO.builder().approvalIdList(approvalIdList).build());
    }

    /**
     * 通过审批实例id获取详情
     *
     * @param approvalId
     *            审批实例id
     * @return {@link R}<{@link ApprovalVo}>
     */
    @ApiOperation("查询审批详情")
    @GetMapping("/approval/{approvalId}")
    R<ApprovalVo> getApprovalById(@PathVariable Long approvalId);

    /**
     * 查询审批流流程节点
     * @param approval 审批流实例列表
     * @return 审批流对应的流程节点
     */
    @ApiOperation("查询审批流流程节点")
    @PostMapping(value ="/approval/all-nodes", consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<List<List<EntireProcessDetailVo>>> getAllProcessDetailList(@RequestBody ApprovalMapDTO approval);

    /**
     * 发起审批
     *
     * @param approvalTemplateCode
     *            审批模板Code
     * @param approval
     *            审批参数
     * @return {@link R}<{@link Long}>
     */
    @PostMapping(value = "/approval/{approvalTemplateCode}", consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<Long> startProcess(@PathVariable String approvalTemplateCode, @RequestBody ApprovalDTO approval);

    /**
     * 发起审批
     *
     * @param approvalTemplateCode
     *            审批模板Code
     * @param approval
     *            审批参数
     * @return {@link R}<{@link Long}>
     */
    @PostMapping(value = "/approval/{approvalTemplateCode}", consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<Long> startProcess(@PathVariable Long approvalTemplateCode, @RequestBody ApprovalDTO approval);

    /**
     * 【撤回审批】(结束审批,类似拒绝 正常是前端调用, 为后端专门开的接口)
     *
     * @param approvalId
     *            审批实例id
     * @param userDTO
     *            用户信息
     * @return {@link R}<{@link Long}>
     */
    @PostMapping(value = "/approval/{approvalId}/revoke", consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<Long> revokeApproval(@PathVariable Long approvalId, @RequestBody UserDTO userDTO);

    /**
     * 审批驳回, 驳回到上一级
     * @param approvalId 审批流实例id
     * @param userId 用户id
     * @param userName 用户名称
     * @return
     */
    default R<Void> approvalRejected(Long approvalId, Long userId, String userName) {
        return approvalRejected(approvalId, userId, userName, null);
    }

    /**
     * 审批驳回, 驳回到上一级
     * @param approvalId 审批流实例id
     * @param userId 用户id
     * @param userName 用户名称
     * @param remark 备注
     * @return
     */
    default R<Void> approvalRejected(Long approvalId, Long userId, String userName, String remark) {
        return approvalRejected(approvalId, ApprovalRejectedDTO.builder()
                .userId(userId)
                .userName(userName)
                .remark(remark)
                .build());
    }

    /**
     * 审批驳回, 驳回到上一级
     * @param approvalId 审批流实例id
     * @param rejected 参数
     * @return
     */
    @PostMapping(value = "/approval/{approvalId}/rejected" , consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<Void> approvalRejected(@PathVariable Long approvalId, @RequestBody ApprovalRejectedDTO rejected);

    /**
     * 根据审批实例查询对应的审批人员，一般用于列表对接
     * @param approvalMap 审批流实例
     * @return 审批实例对应的审批人员
     */
    @PostMapping(value = "/approval/processing" , consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<Map<Long, String>> approvalToMap(@RequestBody ApprovalMapDTO approvalMap);

    /**
     * 默认是分页的内容.使用默认接口即可
     * 
     * @param approvalTemplateId 审批模板Code
     * @param userId 用户ID
     * @param pageNum 页码
     * @param pageSize 页长
     * @return
     */
    @GetMapping("/approval/list")
    R<List<ApprovalVo>> getInstanceStatusList(@RequestParam("approvalTemplateId") Long approvalTemplateId,
        @RequestParam("userId") Long userId, @RequestParam(defaultValue = "1") Integer pageNum,
        @RequestParam(defaultValue = "20") Integer pageSize);

    /**
     * 根据审批流模板和用户查询审批流实例数据
     * @param approvalStatus (审批流模板Code, 用户id列表)
     * @return 审批流实例列表
     */
    @PostMapping(value = "/approval/list" , consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<List<ApprovalVo>> listInstanceStatusList(@RequestBody ApprovalStatusDTO approvalStatus);

    /**
     * 批量查询当前审批人员
     * @param approval 审批流实例id列表
     * @return 每个审批流的审批人员
     */
    @ApiOperation("批量查询当前审批节点")
    @PostMapping(value = "/approval/api/node/batch" , consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<List<ApprovalNodeVO>> listApprovalNode(@RequestBody ApprovalMapDTO approval);

    /**
     * 根据审批流实例id查询当前审批人员
     * @param approvalId 审批流实例id
     * @return 审批人员
     */
    @ApiOperation("单个查询当前审批节点")
    @GetMapping("/approval/api/{approvalId}/node")
    R<ApprovalNodeVO> getApprovalNode(@PathVariable Long approvalId);

    /**
     * 批量发起审批流程
     * @param approvalTemplateCode 审批流模板
     * @param approvalList 发起审批参数
     * @return 发起审批结果
     */
    @PostMapping(value = "/approval/api/approvalTemplate/{approvalTemplateCode}" , consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<List<StartApprovalVO>> startBatchApproval(
            @PathVariable String approvalTemplateCode, @RequestBody List<StartApprovalDTO> approvalList);

    /**
     * 批量审核
     * @param approvalList 审批参数
     * @return 审批结果
     */
    @ApiOperation("批量审核")
    @PostMapping(value ="/approval/api/approval-change" , consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<List<ApprovalOperationVO>> approvalChange(@RequestBody List<ApprovalOperationDTO> approvalList);

    /**
     * 审批并获取下一个审批
     * @param approvalId 审批id
     * @param approval 审批参数
     * @return
     */
    @PostMapping(value = "/approval/{approvalId}/approval-change/next" , consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<NextNotifyVo> approvalChangeAndReturnNextOne(@PathVariable Long approvalId, @RequestBody ApprovalDTO approval);

    /**
     * 检查用户是否有审批权限
     * @param checkPermission 权限检查参数(用户id, 审批流实例id列表)
     * @return 是否有权限
     */
    @ApiOperation("检查用户是否有审批权限")
    @PostMapping(value = "/approval/api/check-permission" , consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
    R<Boolean> checkPermission(@RequestBody CheckPermissionDTO checkPermission);

    /**
     * 发送催办消息（废弃）
     * @param approvalId 审批流实例id
     */
    @Deprecated
    @GetMapping("/reminder/approval/{approvalId}")
    R<Void> sendRemindMessage(@PathVariable Long approvalId);

    /**
     * 催办
     * @param approvalId 审批实例id
     * @param bizType 日志中心-业务类型
     * @return
     */
    @GetMapping("/urge/{approvalId}")
    R<Boolean> urge(@PathVariable Long approvalId, @RequestParam(required = false) String bizType);
}
